package com.tbit.uqbike.tergateway.service.mynetty;

import com.tbit.uqbike.tergateway.config.TerGatewayConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public class TbitNettyServer {

    private static Logger logger = LoggerFactory.getLogger(TbitNettyServer.class);
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    public TbitNettyServer() {
        bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
        workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 5);
    }

    public void service(String IP, int PORT) throws Exception {
        final ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                // TODO Auto-generated method stub
                ch.pipeline().addLast(new TerProtocolPkgDecoder());
                ch.pipeline().addLast(new IdleStateHandler(TerGatewayConfig.TcpCutSec, TerGatewayConfig.TcpCutSec, TerGatewayConfig.TcpCutSec, TimeUnit.SECONDS));
                ch.pipeline().addLast(new NettyPkgHandler());
            }
        });
        bootstrap.option(ChannelOption.SO_BACKLOG, 128)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.SO_RCVBUF, 10 * 1024)
                .option(ChannelOption.SO_SNDBUF, 10 * 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true);
        ChannelFuture f = null;
        try {
            f = bootstrap.bind(IP, PORT).sync();
            logger.info("TCP Server Started Succ.");
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("TCP Server Started Fail.", e);
        }
    }

    public void ws_service(String ip, Integer port) {
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(new WebSocketChannelInitializer());
        bootstrap.option(ChannelOption.SO_BACKLOG, 128)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.SO_RCVBUF, 10 * 1024)
                .option(ChannelOption.SO_SNDBUF, 10 * 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true);
        ChannelFuture f = null;
        try {
            f = bootstrap.bind(ip, port).sync();
            logger.info("TCP Server Started Succ.");
            f.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.error("TCP Server Started Fail.", e);
        }
    }

    public void shutdown() {
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        String IP = "0.0.0.0";
        int PORT = 8888;

        TbitNettyServer tns = new TbitNettyServer();
        logger.info("开始启动TCP服务器...");
        tns.service(IP, PORT);
    }
}
